#include "splitter.h"
namespace win
{
	LRESULT CALLBACK Splitter::WndProc(HWND hwnd, UINT msg,
	 								  WPARAM wParam, LPARAM lParam)
	{
		Splitter * ctl;
	    switch (msg)
		{
			case WM_LBUTTONDOWN:
	  			ctl = (Splitter *) GetWindowLong(hwnd,GWL_USERDATA);
	   			ctl->_dragging = true;
	   			::SetCapture(hwnd);
	   			ctl->RedrawWindow();
	   			break;
			case WM_LBUTTONUP:
	  			ctl = (Splitter *) GetWindowLong(hwnd,GWL_USERDATA);
	   			ctl->_dragging = false;
	   			::ReleaseCapture();
	   			ctl->RedrawWindow();
	   			break;
	  		case WM_MOUSEMOVE:
	  			ctl = (Splitter *) GetWindowLong(hwnd,GWL_USERDATA);
	  			if (ctl && ctl->_dragging)
	  			{
	  				Point p(LOWORD(lParam),HIWORD(lParam));
	  				ctl->ChildToParent(p);
		  			ctl->NotifyParent(ctl->_position==right?p.x:p.y);
	  			}
	  			break;
			case WM_PAINT:
	  			ctl = (Splitter *) GetWindowLong(hwnd,GWL_USERDATA);
	 			ctl->Draw();
	 			break;
		}
		return  DefWindowProc( hwnd,msg,wParam,lParam );
	}

	Splitter::Splitter(Window& anchor, const placement anchor_position,
						const int thick)
	: _anchor(anchor), _position(anchor_position)
	{
		Thickness = thick;
		_dragging = false;
	}

	Splitter::~Splitter()
	{
	}

	void Splitter::Create(Window &parent, const int child_index)
	{
		 _hwnd = 0;
	     _child_index = child_index;
	     const HWND parent_handle = parent.GetHandle();
	     const HINSTANCE instance_handle = reinterpret_cast<HINSTANCE>
	         							(GetWindowLong(parent_handle,GWL_HINSTANCE));
	     static bool is_h_registered = false;
	     static bool is_v_registered = false;
	     char * split_class;
	     if (_position == bottom)
	     {
		    static char * H_SPLIT_CLASS = "h_splitter";
	     	if (!is_h_registered)
	     	{
		     	is_h_registered = true;
			    WNDCLASS wc;
			 	ZeroMemory(&wc,sizeof(wc));
			 	wc.style = CS_HREDRAW|CS_VREDRAW;
			 	wc.hInstance = instance_handle;
			 	wc.hbrBackground = reinterpret_cast <HBRUSH>
	    			(COLOR_MENU + 1);
			 	wc.hCursor = LoadCursor (NULL, IDC_SIZENS);
			 	wc.lpfnWndProc = Splitter::WndProc;
			 	wc.lpszClassName = H_SPLIT_CLASS;
			 	::RegisterClass(&wc);
			}
			split_class = H_SPLIT_CLASS;
		}
	 	else
	    {
		    static char * V_SPLIT_CLASS = "v_splitter";
	     	if (!is_v_registered)
	     	{
		     	is_v_registered = true;
			    WNDCLASS wc;
			 	ZeroMemory(&wc,sizeof(wc));
			 	wc.style = CS_HREDRAW|CS_VREDRAW;
			 	wc.hInstance = instance_handle;
			 	wc.hbrBackground = reinterpret_cast <HBRUSH>
	    				(COLOR_MENU + 1);
			 	wc.hCursor = LoadCursor (NULL, IDC_SIZEWE);
			 	wc.lpfnWndProc = Splitter::WndProc;
			 	wc.lpszClassName = V_SPLIT_CLASS;
			 	::RegisterClass(&wc);
			}
			split_class = V_SPLIT_CLASS;
		};
	 	_hwnd = CreateWindow(split_class,NULL,
	  							WS_CHILD | WS_VISIBLE,
	  							0,0,0,0,
	         					parent_handle,
	         					reinterpret_cast<HMENU> (_child_index),
	  							instance_handle, NULL);
	 	SetPointer(this);
	}


	void Splitter::AdjustLayout()
	{
		Rect parent_rect,target_rect;
		::GetWindowRect(_anchor.GetHandle(),&target_rect);
		Point corner(target_rect.left,target_rect.top);
		::ScreenToClient(GetParentHandle(),&corner);
		target_rect.MoveTo(corner);
		if (_position == bottom)
		{
			target_rect.top = target_rect.bottom;
	  		target_rect.bottom += Thickness;
		}
	 	else
		{
			target_rect.left = target_rect.right;
			target_rect.right += Thickness;
		}
		Move(target_rect);
	}

	void Splitter::Draw()
	{
		if (_dragging)
		{
			PAINTSTRUCT ps;
			HDC hdc = BeginPaint(_hwnd,&ps);
			HPEN pen = CreatePen(PS_SOLID,1,RGB(0,0,0));
			HGDIOBJ old_pen = SelectObject(hdc,pen);
			RECT r;
			GetClientRect(r);
			if (_position == right)
			{
				int mid = r.right >> 1;
				MoveToEx(hdc,mid,0,NULL);
				LineTo(hdc,mid,r.bottom);
	  		}
	    	else
	  		{
				int mid = r.bottom >> 1;
				MoveToEx(hdc,0,mid,NULL);
				LineTo(hdc,r.right,mid);
	  		}
			DeleteObject(SelectObject(hdc,old_pen));
			EndPaint(_hwnd,&ps);
		}
	}
}
